#include "../../Header/AppCore/ObjectTexture.h"
#include "../../../Utilities/Header/TGA.h"

GLuint ObjectTexture::Init(GLenum format, _utInt32 textureCount, char** srcs)
{
	m_Format = format;
	m_TBO_size = textureCount;
	m_strSRCs = String::CpyStringArray(srcs, 0, textureCount);
	return Init();
}

GLuint ObjectTexture::Init(ObjectTexture &objt)
{
	m_TBO_size = objt.GetTBOSize();
	m_TBO = new GLuint[m_TBO_size];
	const GLuint* tbo = objt.GetTBO();
	for (register int i = 0; i < m_TBO_size; i++)
	{
		m_TBO[i] = tbo[i];
	}
	m_TargetTex = objt.GetTextureTarget();
	m_strSRCs = String::CpyStringArray(objt.GetSRCs(), 0, m_TBO_size);
	return Init();
}

GLuint ObjectTexture::Init()
{
	switch (m_Format)
	{
	case GL_TEXTURE_2D:
		return Init2D();
	case GL_TEXTURE_CUBE_MAP:
		return InitCube();
	default:
		return -3;
	}
}
GLuint ObjectTexture::Init2D()
{
	m_TBO = new GLuint[m_TBO_size];
	glGenTextures(m_TBO_size, m_TBO);
	int idx = 0;
	for (int i = m_TargetTex; i < m_TargetTex + m_TBO_size; i++)
	{
		//Load texture data from TGA file
		GLenum eTextureFormat;
		_utInt32 iWidth, iHeight, iBPP;
		char* src = NULL;
		src = TGAImage::LoadTGA(m_strSRCs[idx], &iWidth, &iHeight, &iBPP);

		//Check texture format
		switch (iBPP)
		{
		case 24:
			eTextureFormat = GL_RGB;
			break;
		case 32:
			eTextureFormat = GL_RGBA;
			break;
		default:
			SAFE_DEL_ARRAY(m_TBO);
			SAFE_DEL_ARRAY(src);
			return -3;
		}

		//Bind texture data
		glActiveTexture(GL_TEXTURE0 + idx);
		glBindTexture(GL_TEXTURE_2D, m_TBO[idx]);
		glTexImage2D(GL_TEXTURE_2D, 0, eTextureFormat, iWidth, iHeight, 0, eTextureFormat, GL_UNSIGNED_BYTE, src);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glGenerateMipmap(GL_TEXTURE_2D);

		glActiveTexture(GL_TEXTURE0 + idx);
		glBindTexture(GL_TEXTURE_2D, 0);
		SAFE_DEL_ARRAY(src);
		idx++;
	}
	return 0;
}

GLuint ObjectTexture::InitCube()
{
	return 0;
}

void ObjectTexture::Bind(ObjectShader sha)
{
	switch (m_Format)
	{
	case GL_TEXTURE_2D:
	{
		int idx = 0;
		for (int i = m_TargetTex; i < m_TargetTex + m_TBO_size; i++)
		{
			if (sha.m_Sampler[i] != -1)
			{
				glActiveTexture(GL_TEXTURE0 + idx);
				glBindTexture(GL_TEXTURE_2D, m_TBO[idx]);
				glUniform1i(sha.m_Sampler[i], idx);
			}
			idx++;
		}
	}
		break;
	case GL_TEXTURE_CUBE_MAP:
	{
		if (sha.m_Sampler[0] != -1)
		{
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_CUBE_MAP, m_TBO[0]);
			glUniform1i(sha.m_Sampler[0], 0);
		}
	}
		break;
	default:
		break;
	}
}

void ObjectTexture::UnBind()
{
	switch (m_Format)
	{
	case GL_TEXTURE_2D:
	{
		for (int i = 0; i < m_TBO_size; i++)
		{
			glActiveTexture(GL_TEXTURE0 + i);
			glBindTexture(GL_TEXTURE_2D, 0);
		}
	}
		break;
	case GL_TEXTURE_CUBE_MAP:
	{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
	}
		break;
	default:
		break;
	}
}

void ObjectTexture::Destroy()
{
	glDeleteTextures(m_TBO_size, m_TBO);
	SAFE_DEL(m_TBO);
	SAFE_DEL_ARRAY_POINTER(m_strSRCs, m_TBO_size);
}